<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 一、立即执行函数：声明函数之后，立即调用
        // 语法： (函数)()
        // (function(){
        //     console.log(123)
        // })();

        // 两个变量交换值，借用第三个中间变量
        // (function() {
        //     let a = 10,
        //         b = 20;
        //     let temp = a;
        //     a = b;
        //     b = temp;
        //     console.log(a,b);
        // })();
        // (function(){
        //     console.log(345);
        // })()

        // let a="hello";

        // 立即执行函数的作用：
        // 把一些只用一次的变量放在立即执行函数里面，作为局部变量，不会污染全局环境
        // 注意：1.在立即执行函数前面的内容书写完毕之后，一定要打分好，表示结尾，否则就会和后面的立即执行函数合在一起执行，语法错误
        //      2.立即执行函数不需要函数名


        // 作用域：
        // 1.全局作用域：js全局代码环境
        // 2.局部作用域：大括号产生局部作用域  var声明的变量或者遗漏声明的变量依然是全局变量
        // 3.函数作用域：函数内部就是函数作用域  var声明的变量在函数作用域中是局部变量；遗漏声明在函数作用域中依然是全局变量


        // 十、js代码解析的具体步骤
        // 1.js引擎解析js代码，会在栈空间中产生一个执行上下文栈（Execution Context Stack 简称：ECStack）

        // 数据结构：栈和队列
        // 栈：先进后出（洗碗=>吃饭）
        // 队列：先进先出（排队）

        // 2.首先执行的是全局代码，为了全局代码能够正常执行，需要创建一个全局执行上下文（Global Execution Context 简称：GEC）
        // 并且放入到执行上下文栈中
        // 注意：全局执行上下文每个js文件只有一个，永远不会被销毁
        // 全局执行上下文（GEC）中有两个阶段：
        // （1）建立阶段：创建一个变量对象（Variable Object 简称：VO）=GO（Global Object 全局对象）=window
        // （2）执行阶段:执行全局代码

        // 3.代码执行遇到函数调用，就会创建函数执行上下文（Function Execution Context 简称：FEC），
        // 并且被放入到执行上下文栈中
        // 函数执行上下文（FEC）中有两个阶段
        // （1）建立阶段：
        // 1.1 创建一个变量对象（VO）=AO（Active Object 简称:AO  活动对象）
        // AO={
        // arguements伪数组对象（存放所有实参）
        // 形参变量
        // 函数声明
        // 局部变量
        // }
        // 1.2 作用域链=VO+上级作用域
        // 1.3 this指向
        // （2）执行阶段：执行函数中的每一句代码

        // 4.函数执行完毕之后，会把函数执行上下文（FEC）从执行上下文栈中删除，如果后续再调用该函数，
        // 就再生成一个新的函数执行上下文，然后再放入执行上下文栈中

        // 概念总结：
        // 1.执行上下文栈（Execution Context Stack 简称：ECStack）：js引擎解析js代码的时候，一开始就在栈空间创建的数据结构
        // 2.全局执行上下文（Global Execution Context 简称：GEC）：一开始解析全局代码，就会生成出来，并且放在执行上下文栈的最底部，永远不会被删除
        // 3.函数执行上下文（Function Execution Context 简称：FEC）：每次函数调用的时候，就会生成出来，并且放入执行上下文栈，执行完毕之后，就被删除
        // 4.变量对象（Variable Object 简称：VO）：每一个执行上下文都会被关联到一个变量对象，
        // 在源代码中的arguements伪数组对象、形参变量、函数声明、局部变量都会作为属性被添加到这个变量对象中
        // 5.全局对象（Global Object 简称：GO）：只会出现在全局执行上下文中，等于window对象
        // 6.活动对象（Active Object 简称:AO）：只会出现在函数执行上下文中，一般又会把当前函数执行上下文中的VO称做AO（VO=AO）

        // 总结：在全局执行上下文中：VO=GO=window
        //      在函数执行上下文中：VO=AO


        // 例1：
        // console.log(b);//undefined
        // var a=10;
        // var b=20;
        // console.log(a);//10
        // function test(x){
        //     let k=88;
        //     console.log(x);//55
        // }
        // test(55,6,7,8,9);

        // 例2：
        // console.log(x);//undefined
        // var x=66;
        // function foo(x,y){
        //     console.log(s);//undefined
        //     var s=88;
        //     function min(){
        //         var z=12;
        //         console.log(z);//12
        //     }
        //     console.log(x);//3
        //     console.log(y);//6
        //     min();
        // }
        // console.log(x);//66
        // foo(3,6,8,1);


        // 例3：
        // var m=66;
        // function foo(){
        //     console.log(m);//66
        //     // 因为foo函数中没有m这个变量，就需要到上级作用域中去获取
        //     // foo函数的上级作用域是全局对象（GO=window），因此m=66
        //     // 注意：函数的上级作用域在函数声明的时候就确定了，和函数的声明位置有关，和函数的调用位置无关
        // }
        // function fn(){
        //     var m=99;
        //     foo();
        // }
        // fn();

        // 例4：
        // var n=100;//全局变量
        // function foo(){
        //     n=200;//全局变量
        // }
        // foo();
        // console.log(n);//200

        // 例5：
        // function foo(){
        //     console.log(n);//undefined
        //     // var n:变量提升，把当前变量的作用域提升至当前作用域的最顶端
        //     var n=200;
        //     console.log(n);//200
        // }
        // var n=100;
        // foo();

        // 例6：
        // var n=100;
        // function foo(){
        //     console.log(n);//100
        // }
        // function fn(){
        //     var n=200;
        //     console.log(n);//200
        //     foo();
        // }
        // fn();
        // console.log(n);//100

        // 例7：
        // var a=10;
        // function foo(){
        //     console.log(a);//undefined
        //     // return后面的代码不会指向，但是在代码解析阶段，依然会解析return后面的代码
        //     // 解析代码的时候，变量a依然被解析为局部变量，默认值为undefined
        //     return;
        //     var a=100;
        // }
        // foo();

        // 例8：
        // function foo(){
        //     var a=b=100;
        //     // 相当于
        //     // var a=100;//局部变量
        //     // b=100;//遗漏声明  全局变量
        // }
        // foo();
        // console.log(a);//报错
        // console.log(b);//100
        

        





       
        



    </script>
</body>

</html>